using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using System.Web;
using System.Web.Mail;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

namespace Halide
{
	/// <summary>
	/// The ImageJuggler class contains methods and properties for performing or evaluating bitmap image operations.
	/// </summary>
	sealed public class ImageJuggler
	{
		private static string _version = "2007.12.14A";

		/// <summary>
		/// Return the version number of the class; read-only.
		/// </summary>
		/// <value>
		/// A string with the version number of the class.
		/// </value>
		public static string Version
		{
			get
			{
				return _version;
			}
		}

		/// <summary>
		/// No constructor is necessary.
		/// </summary>
		private ImageJuggler()
	    {
	    }

	    /// <summary>
	    /// Resize an image on disk, constraining proportions
		/// (handles BMP, JPEG, GIF, TIFF, PNG); maintains
		/// transparency of PNG images. Filenames determine
		/// file types used automatically.
	    /// </summary>
		/// <example>
		/// <code>
		/// Rectangle croparea = new Rectangle(0, 0, 0, 0);
		/// string finalPath = Halide.ImageJuggler.ResizeImage("/portfolio/picture01.jpg", 80, 320, 0, "/portfolio/temp/upload.jpg", croparea);
		/// </code>
		/// </example>
	    /// <param name="ImageSavePath">Web-style path with filename for the final resized image.</param>
	    /// <param name="quality">Quality setting from 1 to 100 (for JPEG only; 0 for other types).</param>
	    /// <param name="MaxWidth">How wide to make the image, constraining the aspect ratio (0 ignore this param).
		/// Only one "Max" property can be used at a time - set the other to a zero.</param>
	    /// <param name="MaxHeight">How tall to make the image, constraining the aspect ratio (0 ignore this param).</param>
	    /// <param name="path">Web-style path to the source image file.</param>
	    /// <param name="croparea">Rectangle object (left, top, width, height) to crop image. Leave out for no cropping.</param>
		/// <returns>The web path to the saved file on success, empty string on failure.</returns>
		public static string ResizeImage(string ImageSavePath, int quality, int MaxWidth, int MaxHeight, string path, Rectangle croparea)
		{
			MaxWidth = System.Math.Abs(MaxWidth);
			MaxHeight = System.Math.Abs(MaxHeight);

			if(MaxWidth == 0 && MaxHeight == 0) return (string.Empty);

			int intNewWidth = 0; 
			int intNewHeight = 0; 
			System.Drawing.Image image;

			ImageSavePath = HttpContext.Current.Server.MapPath(ImageSavePath);

			try
			{
				if(croparea.Top == 0 && croparea.Bottom == 0 && croparea.Width == 0 && croparea.Height == 0)
				{
					image = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(path));
				}
				else
				{
					image = CropImage(path, croparea.Width, croparea.Height, croparea.Left, croparea.Top);
				}

				int intOldWidth = image.Width; 
				int intOldHeight = image.Height; 

				if(MaxWidth > 0)
				{
					if (intOldWidth != MaxWidth) 
					{ 
						//set new width and height	
						double dblCoef = (double)MaxWidth / (double)intOldWidth; 

						intNewWidth = Convert.ToInt32(dblCoef * intOldWidth); 
						intNewHeight = Convert.ToInt32(dblCoef * intOldHeight); 
					} 
					else 
					{ 
						intNewWidth = intOldWidth; 
						intNewHeight = intOldHeight; 
					} 
				}

				if(MaxHeight > 0)
				{
					if (intOldHeight != MaxHeight) 
					{ 
						//set new width and height	
						double dblCoef = (double)MaxHeight / (double)intOldHeight; 

						intNewWidth = Convert.ToInt32(dblCoef * intOldWidth); 
						intNewHeight = Convert.ToInt32(dblCoef * intOldHeight); 
					} 
					else 
					{ 
						intNewWidth = intOldWidth; 
						intNewHeight = intOldHeight; 
					} 
				}

	            System.Drawing.Image thumbnail = new Bitmap(intNewWidth, intNewHeight, PixelFormat.Format32bppPArgb);
	            System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(thumbnail);

	            graphic.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
	            graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
	            graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
	            graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
	            graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
	            graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
	            graphic.DrawImage(image, 0, 0, thumbnail.Width, thumbnail.Height);

	            ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();

	            int encoder = 1;

	            switch (Halide.StringJuggler.Right(ImageSavePath, 4).ToLower())
	            {
	                case ".bmp": encoder = 0; break;
	                case ".jpg": encoder = 1; break;
	                case ".gif": encoder = 2; break;
	                case ".tif": encoder = 3; break;
	                case ".png": encoder = 4; break;
	            }

	            switch (Halide.StringJuggler.Right(ImageSavePath, 5).ToLower())
	            {
	                case ".jpeg": encoder = 1; break;
	                case ".tiff": encoder = 3; break;
	            }

	            if (encoder != 1) quality = 100;

	            EncoderParameters encoderParameters;
	            encoderParameters = new EncoderParameters(1);
	            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality);

	            thumbnail.Save(ImageSavePath, info[encoder], encoderParameters);

	            image.Dispose();
	            thumbnail.Dispose();
	            graphic.Dispose();
	            encoderParameters.Dispose();

	            return (ImageSavePath);
	        }
			catch (Exception e)
			{
				return (e.ToString());
			}

		}

		/// <summary>
		/// Resize an image on disk, constraining proportions
		/// (handles BMP, JPEG, GIF, TIFF, PNG); maintains
		/// transparency of PNG images. Filenames determine
		/// file types used automatically.
		/// </summary>
		/// <example>
		/// <code>
		/// string finalPath = Halide.ImageJuggler.ResizeImage("/portfolio/picture01.jpg", 80, 320, 0, "/portfolio/temp/upload.jpg", croparea);
		/// </code>
		/// </example>
		/// <param name="ImageSavePath">Web-style path with filename for the final resized image.</param>
		/// <param name="quality">Quality setting from 1 to 100 (for JPEG only; 0 for other types).</param>
		/// <param name="MaxWidth">How wide to make the image, constraining the aspect ratio (0 ignore this param).
		/// Only one "Max" property can be used at a time - set the other to a zero.</param>
		/// <param name="MaxHeight">How tall to make the image, constraining the aspect ratio (0 ignore this param).</param>
		/// <param name="path">Web-style path to the source image file.</param>
		/// <returns>The web path to the saved file on success, empty string on failure.</returns>
		public static string ResizeImage(string ImageSavePath, int quality, int MaxWidth, int MaxHeight, string path)
		{
			Rectangle croparea = new Rectangle(0, 0, 0, 0);		
			return ResizeImage(ImageSavePath, quality, MaxWidth, MaxHeight, path, croparea);
		}

	    /// <summary>
	    /// Load an image from disk and crop, returning cropped System.Drawing.Image object.
	    /// </summary>
		/// <example>
		/// <code>
		/// Image croppedImage = Halide.ImageJuggler.CropImage("/portfolio/picture01jpg", 320, 0, 0, 0);
		/// </code>
		/// </example>
		/// <param name="path">Web-style path to the source image file.</param>
	    /// <param name="Width">Crop width.</param>
	    /// <param name="Height">Crop height.</param>
	    /// <param name="Left">Left pixel location for starting point.</param>
	    /// <param name="Top">Top pixel location for starting point.</param>
		/// <returns>System.Drawing.Image object cropped.</returns>
		static System.Drawing.Image CropImage(string path, int Width, int Height, int Left, int Top)
		{
			System.Drawing.Image imgPhoto = System.Drawing.Image.FromFile(HttpContext.Current.Server.MapPath(path));
			Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format32bppPArgb);

			bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

			int sourceWidth = imgPhoto.Width;
			int sourceHeight = imgPhoto.Height;

			Graphics grPhoto = Graphics.FromImage(bmPhoto);
	        grPhoto.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
	        grPhoto.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
	        grPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
			grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
			grPhoto.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

			grPhoto.DrawImage(imgPhoto, 
				new Rectangle(0, 0, Width, Height),
				new Rectangle(Left, Top, Width, Height),
				GraphicsUnit.Pixel);

			grPhoto.Dispose();

			return bmPhoto;

		}

	// Outer Identify class
	}

// Outer namespace
}